/*
 * Copyright (c) 2022 FuZhou Lockzhiner Electronic Co., Ltd. All rights reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include "los_task.h"
#include "ohos_init.h"
#include "lz_hardware.h"
#include "picture.h"
#include "lcd.h"
#include "e53_intelligent_street_lamp.h"

#define RET_OK 0
#define RET_ERROR -1
#define GPIO_TEST GPIO0_PA4
#define GPIO_DHT11 GPIO0_PB3 //READ LUM
#define DHT11_ACQUISITION_CYCLE 100 // 读取周期,单位ms

uint32_t humValue = 0; // 存放模拟信号量的变量
uint32_t tempValue = 0;
uint8_t chinese_string1[] = "当前湿度为";
uint8_t chinese_string2[] = "当前温度为";
uint8_t chinese_string3[] = "当前光照为";
uint8_t chinese_string4[] = "天气晴";
uint8_t chinese_string5[] = "下雨了";
uint8_t chinese_string6[] = ":";
uint8_t chinese_string7[] = "℃";




static LzGpioValue dht11_data_get(void)
{
    LzGpioValue value;
    LzGpioGetVal(GPIO_DHT11, &value);
    return value;
}

static int dht11_wait_for_val(int val, int timeout_us)
{
    while (timeout_us--)
    {
        if (dht11_data_get() == val)
            return 0; /* ok */
        LOS_UDelay(1);
    }
    return -1; /* err */
}

static LzGpioValue dht11_wait_ack(void)
{
    int i;
    while (dht11_data_get() && (i < 100))
    {
        i++;
        LOS_UDelay(1);
    }
    if (i > 100)
    {
        return RET_ERROR;
    }
    else
    {
        return RET_OK;
    }
}

void dht11_init(void)
{
    /* 初始化引脚为GPIO */
    LzGpioInit(GPIO_DHT11);
    /* 引脚复用配置为GPIO */
    PinctrlSet(GPIO_DHT11, MUX_FUNC0, PULL_KEEP, DRIVE_LEVEL0);
}

static void dht11_start(void)
{
    LzGpioSetDir(GPIO_DHT11, LZGPIO_DIR_OUT);
    LzGpioSetVal(GPIO_DHT11, LZGPIO_LEVEL_HIGH);
    LOS_UDelay(2);
    LzGpioSetVal(GPIO_DHT11, LZGPIO_LEVEL_LOW);
    LOS_Msleep(20);
    LzGpioSetVal(GPIO_DHT11, LZGPIO_LEVEL_HIGH);
    LOS_UDelay(30);
    LzGpioSetDir(GPIO_DHT11, LZGPIO_DIR_IN);
}

static int dht11_recv_byte(void)
{
    int i;
    int data = 0;

    for (i = 0; i < 8; i++)
    {
        if (dht11_wait_for_val(1, 1000))
        {
            printf("dht11 wait for high data err!\r\n");
            return -1;
        }
        LOS_UDelay(40);
        data <<= 1;
        if (dht11_data_get() == 1)
            data |= 1;

        if (dht11_wait_for_val(0, 1000))
        {
            printf("dht11 wait for low data err!\r\n");
            return -1;
        }
    }

    return data;
}

int dht11_read(int *hum, int *temp)
{
    unsigned char hum_m, hum_n;
    unsigned char temp_m, temp_n;
    unsigned char check;

    dht11_start();

    if (RET_OK != dht11_wait_ack())
    {
        printf("dht11 not ack!\r\n");
        return -1;
    }

    if (0 != dht11_wait_for_val(1, 1000)) /* 等待ACK变为高电平, 超时时间是1000us */
    {
        printf("dht11 wait for ack high err!\r\n");
        return -1;
    }

    if (0 != dht11_wait_for_val(0, 1000)) /* 数据阶段: 等待低电平, 超时时间是1000us */
    {
        printf("dht11 wait for data low err!\r\n");
        return -1;
    }

    hum_m = dht11_recv_byte();
    hum_n = dht11_recv_byte();
    temp_m = dht11_recv_byte();
    temp_n = dht11_recv_byte();
    check = dht11_recv_byte();

    LzGpioSetDir(GPIO_DHT11, LZGPIO_DIR_OUT);
    LzGpioSetVal(GPIO_DHT11, LZGPIO_LEVEL_HIGH);

    if (hum_m + hum_n + temp_m + temp_n == check)
    {
        *hum = hum_m;
        *temp = temp_m;
        return 0;
    }
    else
    {
        printf("dht11 checksum err!\r\n");
        return -1;
    }
}

extern const unsigned char gImage_lingzhi[IMAGE_MAXSIZE_LINGZHI];

/***************************************************************
 * 函数名称: DHT11_process
 * 说    明: DHT11任务
 * 参    数: 无
 * 返 回 值: 无
 ***************************************************************/
void dht11_Process()
{
    
    /*lamp*/
    int lum = 0;

    e53_isl_init();

    int hum, temp;
    int len = 0;
    char buffer[5] = {0};

    
    /* 初始化引脚为GPIO */
    // LzGpioInit(GPIO0_PB4);
    LzGpioInit(GPIO0_PB7);
    /* 引脚复用配置为GPIO */

    PinctrlSet(GPIO0_PB7, MUX_FUNC0, PULL_KEEP, DRIVE_LEVEL0);

    LzGpioSetVal(GPIO0_PB7, LZGPIO_DIR_OUT); // 设置对应的引脚为输出
                                             //    Serial.begin(115200);     //初始化串口波特率115200

    lcd_init();

    dht11_init();
    lcd_fill(0, 0, LCD_W, LCD_H, LCD_WHITE);
    rainInit();
    LzGpioInit(GPIO_TEST);
    /* 引脚复用配置为GPIO */
    PinctrlSet(GPIO_TEST, MUX_FUNC0, PULL_DOWN, DRIVE_LEVEL0);
    LzGpioSetDir(GPIO_TEST, LZGPIO_DIR_IN);
    LzGpioValue io_value;
    while (1)
    {
        /*lamp*/
        lum = e53_isl_read_data();
        printf("luminance value is %.2f\n", lum);

        if (lum < 20)
        {

            isl_light_set_status(ON);
            printf("light on\n");
        }
        else
        {

            isl_light_set_status(OFF);
            printf("light off\n");
        }
        lum = (int)lum;
        /*rain*/
        LzGpioGetVal(GPIO_TEST, &io_value);
        printf("gpio get %d\n", io_value);
        if (dht11_read(&hum, &temp) != 0)
        {
            printf("DHT11 read err!\r\n");
        }
        else
        {
            lcd_show_chinese(0, 10, chinese_string1, LCD_BLACK, LCD_WHITE, 24, 0);
            memset(buffer, 0, sizeof(buffer));
            sprintf(buffer, "%d", hum);
            lcd_show_string(50, 40, buffer, LCD_BLUE, LCD_WHITE, 32, 0);
            lcd_show_string(90, 40, "%rh", LCD_BLUE, LCD_WHITE, 32, 0);
            lcd_show_chinese(120, 10, chinese_string6, LCD_BLACK, LCD_WHITE, 24, 0);
            humValue = memset(buffer, 0, sizeof(buffer));

            lcd_show_chinese(0, 80, chinese_string2, LCD_BLACK, LCD_WHITE, 24, 0);
            memset(buffer, 0, sizeof(buffer));
            sprintf(buffer, "%d", temp);
            lcd_show_string(50, 120, buffer, LCD_BLUE, LCD_WHITE, 32, 0);
            lcd_show_chinese(90, 120, chinese_string7, LCD_BLUE, LCD_WHITE, 32, 0);
            lcd_show_chinese(120, 80, chinese_string6, LCD_BLACK, LCD_WHITE, 24, 0);
            tempValue = memset(buffer, 0, sizeof(buffer));

            lcd_show_chinese(0, 160, chinese_string3, LCD_BLACK, LCD_WHITE, 24, 0);
            memset(buffer, 0, sizeof(buffer));
            sprintf(buffer, "%d", lum);
            lcd_show_string(50, 190, buffer, LCD_BLUE, LCD_WHITE, 32, 0);
            lcd_show_string(100, 190, "lx", LCD_BLUE, LCD_WHITE, 32, 0);
            lcd_show_chinese(120, 160, chinese_string6, LCD_BLACK, LCD_WHITE, 24, 0);
            tempValue = memset(buffer, 0, sizeof(buffer));
            if (io_value != 1)
            {
                lcd_show_chinese(0, 230, chinese_string5, LCD_BLACK, LCD_WHITE, 32, 0);
                WindowOpen();
                IoTPwmStart(0,15,50);
            }
            else
            {
                lcd_show_chinese(0, 230, chinese_string4, LCD_BLACK, LCD_WHITE, 32, 0);
                WindowClose();
                IoTPwmStart(0,10,50);
                
                
            }

            printf("DHT11 : %d humidity, %d temperature\r\n", hum, temp);
        }
        LOS_Msleep(DHT11_ACQUISITION_CYCLE);
    }
}

/***************************************************************
 * 函数名称: DHT11_example
 * 说    明: 开机自启动调用函数
 * 参    数: 无
 * 返 回 值: 无
 ***************************************************************/
void dht11_example()
{
    unsigned int thread_id;
    TSK_INIT_PARAM_S task = {0};
    unsigned int ret = LOS_OK;

    task.pfnTaskEntry = (TSK_ENTRY_FUNC)dht11_Process;
    task.uwStackSize = 2048;
    task.pcName = "dht11 process";
    task.usTaskPrio = 24;
    ret = LOS_TaskCreate(&thread_id, &task);
    if (ret != LOS_OK)
    {
        printf("Falied to create task ret:0x%x\n", ret);
        return;
    }
}

APP_FEATURE_INIT(dht11_example);
